package client;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * Creates the main GUI window when client starts
 * 
 * @author Tobias Robinson
 */  
public class ClientView extends JFrame {
    private int framePositionX;
    private int framePositionY;

    private JMenuBar menuBar = new JMenuBar();
    //menus
    private JMenu menu = null;
    private JMenu flightMenu = null;
    private JMenu userMenu = null;
    private JMenu managerMenu = null;
    private JMenu adminMenu = null;

    private Rectangle frameBounds = null;
    private JScrollPane statusScrPane = new JScrollPane(statusField);
    private static JTextArea statusField = new JTextArea(5,0);
    private JScrollPane tableScrPane = new JScrollPane();

    private static ClientView client;

    
    /**
     * Creates the main GUI window when program starts
     */  
    public ClientView() {
        super("Client");
        setSize(650,450);

        //initial setup
        setContent();

        //indent first menu
        menuBar.add(Box.createRigidArea(new Dimension(10,0)));

        //scrollpane for the status text field        
        statusScrPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        statusScrPane.setBorder(BorderFactory.createLoweredBevelBorder());
        
        // set status field properties        
        statusField.setEditable(false);
        statusField.setLineWrap(true);
        statusField.setWrapStyleWord(true);   
        
        // center the main window        
        Dimension screenSize = getToolkit().getScreenSize();
        frameBounds = getBounds();
        framePositionX = (screenSize.width - frameBounds.width)/2;
        framePositionY = (screenSize.height - frameBounds.height)/2;
        setLocation(framePositionX, framePositionY);

        //sets the window to visible
        setVisible(true);

        //anonymous inner class to terminate program when window is closed
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                try {
                    ClientThread.closeConnection();
                } catch (IOException ex) {
                    Logger.getLogger(ClientView.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
    
    /**
     * Places the given window approximately at the center of the screen 
     * 
     * @param w    window to be centered, can be used on other windows
     */       
    public void centerWindow(Window w) {
        Rectangle winBounds = w.getBounds();
        w.setLocation(framePositionX + (frameBounds.width - winBounds.width)/2, 
		      framePositionY + (frameBounds.height - winBounds.height)/2);
    }
        
    /**
     * Adds the given string to the status text area
     * 
     * @param s    string added to text area
     */ 
    public void updateStatusBar(String s) {
        
	// trim() removes whitespace and control characters at both ends of the string        
	statusField.append(s.trim() + "\n"); 

	// This informs the scroll pane to update itself and its scroll bars.
	// The scroll pane does not always automatically scroll to the message that was
	// just added to the text area. This line guarantees that it does.        
	statusField.revalidate();
    }    
   
    /**
     * Adds the given JTable into tableScrPane
     * 
     * @param data  JTable to be viewed on screen
     */ 
    public void addTable(JTable data) {
	tableScrPane.setViewportView(data);
    }
    /**
     * Creates a menu and adds items in a list
     *
     * @param mb    the name of the menu bar used for its location
     */
    public void menuSetup(JMenuBar mb) {

            //first menu
            menu = new JMenu("Login");
            menu.setMnemonic(KeyEvent.VK_L);

            //menu items
            createMenuItem(menu, "Login Manager...",
                   KeyEvent.VK_L, "LoginManager");
            createMenuItem(menu, "Login Admin...",
                   KeyEvent.VK_L, "LoginAdmin");
            createMenuItem(menu, "Login User...",
                   KeyEvent.VK_L, "LoginUser");
            createMenuItem(menu, "Logout...",
                   KeyEvent.VK_F, "Logout");
            createMenuItem(menu, "Add User...",
                   KeyEvent.VK_A, "AddUser");            
            mb.add(menu);
            
            flightMenu = new JMenu("Flights");
            flightMenu.setMnemonic(KeyEvent.VK_F);

            createMenuItem(flightMenu, "All Flights...",
                   KeyEvent.VK_F, "Flights");
            createMenuItem(flightMenu, "Search Flights...",
                   KeyEvent.VK_F, "SearchFlight");
            mb.add(flightMenu);

            userMenu = new JMenu("User");
            userMenu.setMnemonic(KeyEvent.VK_U);

            createMenuItem(userMenu, "Edit User...",
                   KeyEvent.VK_E, "EditUser");
            createMenuItem(userMenu, "Delete User...",
                   KeyEvent.VK_D, "DeleteUser");
            createMenuItem(userMenu, "Purchase Tickets...",
                   KeyEvent.VK_F, "Purchase");

            managerMenu = new JMenu("Manager");
            managerMenu.setMnemonic(KeyEvent.VK_M);

            createMenuItem(managerMenu, "Users Connected...",
                   KeyEvent.VK_U, "UsersConnected");
            createMenuItem(managerMenu, "Add Promo...",
                    KeyEvent.VK_P, "AddPromo");
            createMenuItem(managerMenu, "Edit GST...",
                    KeyEvent.VK_G, "EditGST");
            createMenuItem(managerMenu, "Add Flight...",
                   KeyEvent.VK_A, "AddFlight");
            createMenuItem(managerMenu, "Edit Flight...",
                    KeyEvent.VK_E, "EditFlight");
            createMenuItem(managerMenu, "Delete Flight...",
                    KeyEvent.VK_D, "DeleteFlight");
            createMenuItem(managerMenu, "Add Airport...",
                    KeyEvent.VK_A, "AddAirport");
            createMenuItem(managerMenu, "Edit Airport...",
                    KeyEvent.VK_E, "EditAirport");
            createMenuItem(managerMenu, "Delete Airport...",
                    KeyEvent.VK_D, "DeleteAirport");            

            adminMenu = new JMenu("Admin");
            adminMenu.setMnemonic(KeyEvent.VK_A);

            createMenuItem(adminMenu, "Create Mananager Account...",
                   KeyEvent.VK_U, "AddMan");
            createMenuItem(adminMenu, "Edit Manager Account...",
                   KeyEvent.VK_A, "EditMan");
            createMenuItem(adminMenu, "Delete Manager Account...",
                    KeyEvent.VK_E, "DeleteMan");
    }

    /**
     * Creates a menu item and adds it to the given menu.
     *
     * @param menu      the menu name the item is associated with
     * @param label     name that appears in the menu view
     * @param nmonic    Key shortcut key used to access menu item
     * @param action    Command command name to run in MenuController
     */
    private JMenuItem createMenuItem(JMenu menu, String label, int mnemonicKey, String actionCommand) {
        JMenuItem menuItem = new JMenuItem(label);

        if (mnemonicKey > 0) {
            menuItem.setMnemonic(mnemonicKey);
        }

        if (actionCommand.length() > 0) {
            menuItem.setActionCommand(actionCommand);
        }

        menu.add(menuItem);
        return menuItem;
    }
    
    /**
     * Creates a menu and adds items in a list
     * 
     * @param mb    the name of the menu bar used for its location
     */  

    public void setMenu(String menuName) {
        menu = new JMenu(menuName);
    }

    /**
     * registers the controllers for all items in each menu. This
     * method should only be executed once.
     */    
    public void registerControllers() {
        JMenuItem menuItem;

        // MenuController handles events on menu items (i.e. when they are clicked)

        ClientMenuController mc = new ClientMenuController(this);

        for (int i = 0; i < menu.getItemCount(); i++) {
            menuItem = menu.getItem(i);
            menuItem.addActionListener(mc);
        }

        for (int i = 0; i < flightMenu.getItemCount(); i++) {
            menuItem = flightMenu.getItem(i);
            menuItem.addActionListener(mc);
        }

        for (int i = 0; i < userMenu.getItemCount(); i++) {
            menuItem = userMenu.getItem(i);
            menuItem.addActionListener(mc);
        }

        for (int i = 0; i < managerMenu.getItemCount(); i++) {
            menuItem = managerMenu.getItem(i);
            menuItem.addActionListener(mc);
        }

        for (int i = 0; i < adminMenu.getItemCount(); i++) {
            menuItem = adminMenu.getItem(i);
            menuItem.addActionListener(mc);
        }
    }
    /**
     * Prints a message in the statusField
     * 
     * @param message   message to be printed
     */ 
    public static void printMessage(String message) {
        String mess = message;
        statusField.append(mess);
    }

    public void setView(String viewType) {
        getContentPane().removeAll();
        menuBar.removeAll();
        setContent();

        if(viewType == "user") {
            menuBar.add(userMenu);
        }
        if(viewType == "man") {
            menuBar.add(managerMenu);
        }
        if(viewType == "admin") {
            menuBar.add(adminMenu);
        }

        validate();
        repaint();
        setVisible(true);
    }

    public static ClientView getInstance() {
        if (client == null) {
            client = new ClientView();
        }
        return client;
    }

    private void setContent() {
        //content pane
        //components spaced 10pixels apart
        JPanel contentPane = new JPanel(new BorderLayout(0, 10));
        setContentPane(contentPane);
        //space around the content pane
        contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        // add the panes to the content pane
        contentPane.add(tableScrPane, BorderLayout.CENTER);
        contentPane.add(statusScrPane, BorderLayout.NORTH);

        //setup menubar
        setJMenuBar(menuBar);
        menuSetup(menuBar);

        //registers the controllers
        registerControllers();

    }
}

